﻿using Dapper.Contrib.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace uowDemo
{
    public static class SqlGenerator
    {
        public static string GenerateInsertSql<T>(T entity)
        {
            var sb = new StringBuilder();
            var columns = GetColumns(entity.GetType());
            sb.AppendFormat("INSERT INTO {0} ({1}) VALUES ({2})",
                GetTableName(entity.GetType()),
                string.Join(", ", columns.Select(c => c.Name)),
                string.Join(", ", columns.Select(c => "@" + c.Name)));

            return sb.ToString();
        }

        public static string GenerateUpdateSql<T>(T entity)
        {
            var sb = new StringBuilder();
            var columns = GetColumns(entity.GetType());
            var idProperty = GetIdProperty(entity.GetType());

            sb.AppendFormat("UPDATE {0} SET {1} WHERE {2} = @{3}",
                GetTableName(entity.GetType()),
                string.Join(", ", columns.Where(c => c.Name != idProperty.Name).Select(c => c.Name + " = @" + c.Name)),
                idProperty.Name, idProperty.Name);

            return sb.ToString();
        }

        public static string GenerateDeleteSql<T>(T entity)
        {
            var sb = new StringBuilder();
            var idProperty = GetIdProperty(entity.GetType());

            sb.AppendFormat("DELETE FROM {0} WHERE {1} = @{2}",
                GetTableName(entity.GetType()),
                idProperty.Name,
                idProperty.Name);

            return sb.ToString();
        }

        private static List<PropertyInfo> GetColumns(Type type)
        {
            return type.GetProperties().Where(p => p.GetCustomAttribute<ColumnAttribute>() != null && p.GetCustomAttribute<AutoGeneratedAttribute>() == null).ToList();
        }

        private static PropertyInfo GetIdProperty(Type type)
        {
            return type.GetProperties().FirstOrDefault(p => p.GetCustomAttribute<KeyAttribute>() != null);
        }

        private static string GetTableName(Type type)
        {
            return type.GetCustomAttribute<TableAttribute>()?.Name ?? type.Name;
        }
    }
}
